/*******************************************************************************
  * 文件：OS_Queue.c
  * 作者：zyz
  * 版本：v2.0.1
  * 日期：2020-03-24
  * 说明：队列
*******************************************************************************/

/* 头文件 *********************************************************************/
#include <string.h>
#include "OS_Queue.h"

/* 宏定义 *********************************************************************/
/* 类型定义 *******************************************************************/
/* 变量定义 *******************************************************************/
/* 函数声明 *******************************************************************/
// 从队列取出元素
static Bool OS_QueueTake(QueueHandle_tps psQueue, void *pvElement, Bool bRemove);

/* 函数定义 *******************************************************************/

/*******************************************************************************
  * 函数名：OS_QueueInit
  * 功  能：初始化队列
  * 参  数：QueueHandle_tps psQueue  - 队列句柄
  *         void *pvDataBuffer       - 数据缓冲区指针
  *         U16 u16QueueSize         - 队列大小
  *         U16 u16ElementSize       - 元素大小
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void OS_QueueInit(QueueHandle_tps psQueue, void *pvDataBuffer,
                  U16 u16QueueSize, U16 u16ElementSize)
{
    // 初始化头和尾索引，元素个数
    psQueue->u16HeadIndex   = 0;
    psQueue->u16TailIndex   = 0;
    psQueue->u16ElementsNum = 0;

    // 初始化数据缓冲区，队列大小，元素大小
    psQueue->pvDataBuffer   = pvDataBuffer;
    psQueue->u16QueueSize   = u16QueueSize;
    psQueue->u16ElementSize = u16ElementSize;
}

/*******************************************************************************
  * 函数名：OS_QueueAdd
  * 功  能：向队列添加元素
  * 参  数：QueueHandle_tps psQueue - 队列句柄
  *         void *pvElement         - 元素指针
  * 返回值：添加结果
  * 说  明：无
*******************************************************************************/
Bool OS_QueueAdd(QueueHandle_tps psQueue, void *pvElement)
{
    Bool bResult = TRUE;
    U32 u32Offset = 0;
    void *pvBufferData;

    // 队列未满
    if(psQueue->u16ElementsNum < psQueue->u16QueueSize)
    {
        // 计算头元素数据的存储地址
        u32Offset = psQueue->u16HeadIndex;
        u32Offset = u32Offset * (psQueue->u16ElementSize);
        pvBufferData = (void *)((U8*)psQueue->pvDataBuffer + u32Offset);

        // 复制元素到队列
        memcpy(pvBufferData, pvElement, psQueue->u16ElementSize);

        // 更新头索引
        psQueue->u16HeadIndex++;
        if(psQueue->u16HeadIndex >= psQueue->u16QueueSize)
        {
            // 索引溢出，重置为0
            psQueue->u16HeadIndex = 0;
        }

        // 更新元素个数
        (psQueue->u16ElementsNum)++;
    }
    // 队列满了
    else
    {
        // 添加失败
        bResult = FALSE;
    }

    // 返回结果
    return bResult;
}

/*******************************************************************************
  * 函数名：OS_QueueTake
  * 功  能：从队列取出元素
  * 参  数：QueueHandle_tps psQueue - 队列句柄
  *         void *pvElement         - 元素指针
  *         Bool bRemove            - 移除元素
  * 返回值：执行结果，TRUE成功，FALSE失败
  * 说  明：无
*******************************************************************************/
static Bool OS_QueueTake(QueueHandle_tps psQueue, void *pvElement, Bool bRemove)
{
    Bool bResult = TRUE;
    U32 u32Offset = 0;
    void *pvBufferData;

    // 队列非空
    if(psQueue->u16ElementsNum > 0)
    {
        // 计算尾元素的存储地址偏移量
        u32Offset = psQueue->u16TailIndex;
        u32Offset = u32Offset * (psQueue->u16ElementSize);
        pvBufferData = (void *)((U8*)psQueue->pvDataBuffer + u32Offset);

        // 从队列中复制元素
        memcpy(pvElement, pvBufferData, psQueue->u16ElementSize);

        // 取出元素后从队列移除
        if(bRemove == TRUE)
        {
            // 更尾索引
            psQueue->u16TailIndex++;
            if(psQueue->u16TailIndex >= psQueue->u16QueueSize)
            {
                // 索引溢出，重置为0
                psQueue->u16TailIndex = 0;
            }

            // 更新元素个数
            (psQueue->u16ElementsNum)--;
        }
    }
    // 队列是空的
    else
    {
        // 取出失败
        bResult = FALSE;
    }

    // 返回结果
    return (bResult);
}

/*******************************************************************************
  * 函数名：OS_QueueRemove
  * 功  能：从队列取出元素并移除
  * 参  数：QueueHandle_tps psQueue - 队列句柄
  *         void *pvElement         - 元素指针
  * 返回值：执行结果，TRUE成功，FALSE失败
  * 说  明：无
*******************************************************************************/
Bool OS_QueueRemove(QueueHandle_tps psQueue, void *pvElement)
{
    // 从队列取出元素并移除
    return OS_QueueTake(psQueue, pvElement, TRUE);
}

/*******************************************************************************
  * 函数名：OS_QueuePeek
  * 功  能：从队列取出元素不移除
  * 参  数：QueueHandle_tps psQueue - 队列句柄
  *         void *pvElement         - 元素指针
  * 返回值：执行结果，TRUE成功，FALSE失败
  * 说  明：无
*******************************************************************************/
Bool OS_QueuePeek(QueueHandle_tps psQueue, void *pvElement)
{
    // 从队列取出元素不移除
    return OS_QueueTake(psQueue, pvElement, FALSE);
}

/*******************************************************************************
  * 函数名：OS_QueueGetElementsNum
  * 功  能：获取元素个数
  * 参  数：QueueHandle_tps psQueue - 队列句柄
  * 返回值：元素个数
  * 说  明：无
*******************************************************************************/
U16 OS_QueueGetElementsNum(QueueHandle_tps psQueue)
{
    // 返回元素个数
    return (psQueue->u16ElementsNum);
}

/***************************** 文件结束 ***************************************/
